var Amqp = require('../amqp').Amqp,
    Handler = require('../handlers/channel').Channel;
/**
 *
 * @exports Channel as impl.Channel
 * @class
 * @extends events.EventEmitter
 * @param connection
 */
function Channel(/**impl.Connection*/connection){
    var channel = this, handler = this.handler = new Handler(connection.handler);
    /**
     * Signal that the channel is ready.
     *
     * This method signals to the client that the channel is ready for use.
     *
     * @name Channel#open
     * @event
     */
    handler.addListener('Amqp.Channel.OpenOk', function(){
        channel.emit('open');
    });
    /**
     * Send a non-fatal warning message.
     *
     * This method allows the server to send a non-fatal warning to the client. This is used for
     * methods that are normally asynchronous and thus do not have confirmations, and for which the
     * server may detect errors that need to be reported. Fatal errors are handled as channel or
     * connection exceptions; non-fatal errors are sent through this method.
     *
     * @name Channel#alert
     * @event
     * @param {Number} replyCode The reply code. The AMQ reply codes are defined in AMQ RFC 011.
     * @param {String} replyText The localised reply text.  This text can be logged as an aid to
     *   resolving issues.
     * @param {Object} details A set of fields that provide more information about the problem. The
     *      meaning of these fields are defined on a per-reply-code basis (TO BE DEFINED).
     */
    handler.addListener('Amqp.Channel.Alert', function(frame){
        var a = frame.method.arguments;
        channel.emit('alert', a.replyCode, a.replyText, a.details);
    });
    /**
     * Enable/disable flow from peer.
     *
     * This method asks the peer to pause or restart the flow of content data. This is a simple
     * flow-control mechanism that a peer can use to avoid oveflowing its queues or otherwise
     * finding itself receiving more messages than it can process. Note that this method is not
     * intended for window control. The peer that receives a request to stop sending content should
     * finish sending the current content, if any, and then wait until it receives a Flow restart
     * method.
     *
     * @name Channel#flow
     * @event
     * @param {Boolean} active If <code>true</code>, the peer starts sending content frames.
     *      If <code>false</code>, the peer stops sending content frames.
     */
    handler.addListener('Amqp.Channel.Flow', function(frame){
        var active = frame.method.arguments.active;
        this.call(Amqp.Class.Channel, Amqp.Class.Channel.FlowOk, { active: active });
        channel.emit('flow', active);
    });
    handler.addListener('Amqp.Channel.FlowOk', function(frame){
        channel.emit('flow', frame.method.arguments.active);
    });
    /**
     * Request a channel close.
     *
     * This method indicates that the sender wants to close the channel. This may be due to
     * internal conditions (e.g. a forced shut-down) or due to an error handling a specific method,
     * i.e. an exception. When a close is due to an exception, the sender provides the class and
     * method id of the method which caused the exception.
     *
     * @name Channel#close
     * @event
     * @param {Number} replyCode The reply code. The AMQ reply codes are defined in AMQ RFC 011.
     * @param {String} replyText The localised reply text.  This text can be logged as an aid to
     *   resolving issues.
     * @param {Number} classId
     * @param {Number} methodId
     */
    handler.addListener('Amqp.Channel.Close', function(frame){
        this.call(Amqp.Class.Channel, Amqp.Class.Channel.CloseOk);
        var a = frame.method.arguments;
        channel.emit('close', a.replyCode, a.replyText, a.classId, a.methodId);
    });

    handler.addListener('Amqp.Channel.CloseOk', function(){
        channel.emit('close');
    });
}
require('sys').inherits(Channel, require('events').EventEmitter);
Object.defineProperty(Channel.prototype, 'channelId', {
    get: function(){
        return this._channelId;
    },
    set: function(channelId){
        if ('_channelId' in this && this._channelId == channelId) return;
        this.handler.channelId = channelId;
        this._channelId = channelId;
    }
});
/**
 * Open a channel for use.
 *
 * This method opens a virtual connection (a channel).
 *
 * @param outOfBand Configures out-of-band transfers on this channel. The syntax and meaning of
 *      this field will be formally defined at a later date.
 */
Channel.prototype.open = function(/**String*/outOfBand){
    this.handler.call(Amqp.Class.Channel, Amqp.Class.Channel.Open, { outOfBand: outOfBand });
};
/**
 * Request a channel close.
 *
 * This method indicates that the sender wants to close the channel. This may be due to internal
 * conditions (e.g. a forced shut-down) or due to an error handling a specific method, i.e. an
 * exception. When a close is due to an exception, the sender provides the class and method id of
 * the method which caused the exception.
 *
 * @param replyCode The reply code. The AMQ reply codes are defined in AMQ RFC 011.
 * @param replyText The localised reply text. This text can be logged as an aid to resolving
 *      issues.
 * @param classId
 * @param methodId
 */
Channel.prototype.close = function(/**Number*/replyCode, /**String*/replyText, /**Number*/classId,
        /**Number*/methodId){
    this.handler.call(Amqp.Class.Channel, Amqp.Class.Channel.Close, { replyCode: replyCode,
        replyText: replyText, classId: classId, methodId: methodId });
};
/**
 * Enable/disable flow from peer.
 *
 * This method asks the peer to pause or restart the flow of content data. This is a simple
 * flow-control mechanism that a peer can use to avoid oveflowing its queues or otherwise finding
 * itself receiving more messages than it can process. Note that this method is not intended for
 * window control. The peer that receives a request to stop sending content should finish sending
 * the current content, if any, and then wait until it receives a Flow restart method.
 *
 * @param active If <code>true</code>, the peer starts sending content frames. If
 *      <code>false</code>, the peer stops sending content frames.
 */
Channel.prototype.flow = function(/**Boolean*/active){
    this.handler.call(Amqp.Class.Channel, Amqp.Class.Channel.Flow, { active: active });
};
exports.Channel = Channel;
